#ifndef VEC4_H
#define VEC4_H

#include<iostream>
#include<windows.h>

//template class for vector4 int homogeneous coordinate
template<class T>
class Vec4
{
public:
	T x, y, z, w;



	Vec4<T>(T _x, T _y, T _z);
	Vec4<T>(T _x, T _y, T _z, T _w);

	Vec4<T>() {
		x = 0; y = 0; z = 0;
		w = 1;
	}

	Vec4<T> operator+(const Vec4<T>& vec) const;
	Vec4<T> operator-(const Vec4<T>& vec) const;
	Vec4<T> operator*(float f) const;
	Vec4<T> operator/(float f) const;

	float Length();
	float LengthSquared();

	Vec4& Normalize();

	float static Dot(const Vec4<T> lv, const Vec4<T> rv);
	float Dot(const Vec4<T>& vec);

	Vec4<T> static Cross(const Vec4<T>& lv, const Vec4<T>& rv);
	Vec4<T> static Lerp(const Vec4<T>& lv, const Vec4<T>& rv,float t);


	void standard() {
		if (w == 0) return;
		x /= w;
		y /= w;
		z /= w;
		w = 1;
	}

};


using Vec4f = Vec4<float>;
using Vec4i = Vec4<int>;
using Vec4d = Vec4<double>;




//vector2 class for texture
class Vec2 {
public:

	float x, y;

	Vec2() { x = y = 0; }

	Vec2(float fx, float fy) {
		x = fx;
		y = fy;
	}

	~Vec2() {}


	Vec2 operator + (const Vec2& right) const
	{
		return Vec2(x + right.x, y + right.y);
	}
	Vec2 operator - (const Vec2& right) const
	{
		return Vec2(x - right.x, y - right.y);
	}
	Vec2 operator * (float value) const
	{
		return Vec2(x * value, y * value);
	}
	Vec2 operator / (float value) const
	{
		return Vec2(x / value, y / value);
	}
	

};





template<class T>
 Vec4<T>::Vec4(T _x, T _y, T _z)
{
	x = _x;
	y = _y;
	z = _z;
	w = 1;
}

template<class T>
Vec4<T>::Vec4(T _x, T _y, T _z, T _w)
{
	x = _x;
	y = _y;
	z = _z;
	w = _w;
}

template<class T>
 Vec4<T> Vec4<T>::operator+(const Vec4<T>& vec) const
{
	Vec4<T> returnValue(x + vec.x, y + vec.y, z + vec.z);
	return returnValue;
}

template<class T>
Vec4<T> Vec4<T>::operator-(const Vec4<T>& vec) const
{
	Vec4<T> returnValue(x - vec.x, y - vec.y, z - vec.z);
	return returnValue;
}

template<class T>
Vec4<T> Vec4<T>::operator*(float f) const
{
	Vec4<T> returnValue(x * f, y * f, z * f);
	return returnValue;
}

template<class T>
Vec4<T> Vec4<T>::operator/(float f) const
{
	Vec4<T> returnValue(x / f, y / f, z / f);
	return returnValue;
}

template<class T>
float Vec4<T>::Length()
{
	return sqrt(LengthSquared());
}

template<class T>
float Vec4<T>::LengthSquared()
{
	return Dot(*this, *this);
}

template<class T>
Vec4<T>& Vec4<T>::Normalize()
{
	*this = *this / Length();
	return *this;
}

template<class T>
float Vec4<T>::Dot(const Vec4<T> lv, const Vec4<T> rv)
{
	return lv.x * rv.x + lv.y * rv.y + lv.z * rv.z;
}

template<class T>
float Vec4<T>::Dot(const Vec4<T>& vec)
{
	return x * vec.x + y * vec.y + z * vec.z;
}

template<class T>
Vec4<T> Vec4<T>::Cross(const Vec4<T>& left, const Vec4<T>& right)
{
	float valueX = left.y * right.z - left.z * right.y;
	float valueY = left.z * right.x - left.x * right.z;
	float valueZ = left.x * right.y - left.y * right.x;
	Vec4<T> returnValue(valueX, valueY, valueZ);
	return returnValue;
}

template<class T>
Vec4<T> Vec4<T>::Lerp(const Vec4<T>& lv, const Vec4<T>& rv, float t)
{
	return lv+(rv-lv)*t;
}






#endif // !VEC4_H


